home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / dev / lang / Python152_Src.lha / Python152_Source / Amiga / strftime.c < prev    next >
C/C++ Source or Header  |  1999-04-27  |  9KB  |  311 lines

  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4. #include <time.h>
  5. #include <locale.h>
  6. #include <libraries/locale.h>
  7. #include <proto/locale.h>
  8. #include <proto/exec.h>
  9. #include <constructor.h>
  10.  
  11. #define ADDS(st)  tmp=strftime(s,maxsize-size,(st),timeptr);break;
  12.  
  13. #define ADDN(a,b) tmp=strfnumb(s,maxsize-size,(a),(b));break;
  14.  
  15. #define STOR(c)   if(++size<=maxsize)*s++=(c);
  16.  
  17. #define STR(a) \
  18. (__localevec[LC_TIME-1]==NULL?strings[(a)-1]:GetLocaleStr(__localevec[LC_TIME-1],(a)))
  19.  
  20. #define strlen_plus_one(s) strlen(s)+1
  21.  
  22.  
  23.  
  24. /***************** Locale stuff ******************/
  25.  
  26. /* This is the vector of Locales for the different locale types.
  27.  * Since the default locale is not NULL, NULL means "C" locale.
  28.  * This is the default if locale.library could not be opened
  29.  * or setlocale is never referenced.
  30.  */
  31.  
  32. static struct Locale *__localevec[5]=
  33. { NULL,NULL,NULL,NULL,NULL };
  34.  
  35. /* If you need __localevec you need LocaleBase and vice versa.
  36.  */
  37. struct Library *LocaleBase=NULL;
  38.  
  39. static unsigned char *__decimalpoint=".";
  40. static struct lconv __lconv_strftime;
  41. static long __gmtoffset;
  42.  
  43.  
  44. /* All calendar strings */
  45. static const unsigned char *strings[]=
  46. { "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday",
  47.   "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
  48.   "January","February","March","April","May","June",
  49.   "July","August","September","October","November","December",
  50.   "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",
  51.   "","","AM","PM" };
  52.  
  53. static size_t strfnumb(char *s,size_t maxsize,signed int places,size_t value)
  54. { size_t size=0;
  55.   if(places>1)
  56.     size=strfnumb(s,maxsize,places-1,value/10);
  57.   else if(value>=10)
  58.     size=strfnumb(s,maxsize,places+1,value/10);
  59.   else
  60.     while ((places++<-1) && (++size<=maxsize)) s[size-1]=' ';
  61.   if(++size<=maxsize)
  62.     s[size-1]=(value%10+'0');
  63.   return size;
  64. }
  65.  
  66. size_t strftime(char *s,size_t maxsize,const char *format,const struct tm *timeptr)
  67. { size_t size=0,tmp;
  68.   while(*format)
  69.   { if(*format=='%')
  70.     { tmp=0;
  71.       switch(*++format)
  72.       { case 'a':
  73.           ADDS(STR(ABDAY_1+timeptr->tm_wday));
  74.         case 'b':
  75.         case 'h':
  76.           ADDS(STR(ABMON_1+timeptr->tm_mon));
  77.         case 'c':
  78.           ADDS("%m/%d/%y");
  79.         case 'd':
  80.           ADDN(2,timeptr->tm_mday);
  81.         case 'e':
  82.           ADDN(-2,timeptr->tm_mday);
  83.         case 'j':
  84.           ADDN(3,timeptr->tm_yday+1);
  85.         case 'k':
  86.           ADDN(-2,timeptr->tm_hour);
  87.         case 'l':
  88.           ADDN(-2,timeptr->tm_hour%12+(timeptr->tm_hour%12==0)*12);
  89.         case 'm':
  90.           ADDN(2,timeptr->tm_mon+1);
  91.         case 'p':
  92.           ADDS(STR(AM_STR+(timeptr->tm_hour>=12)));
  93.         case 'r':
  94.           ADDS("%I:%M:%S %p");
  95.         case 'w':
  96.           ADDN(1,timeptr->tm_wday);
  97.         case 'x':
  98.           ADDS("%m/%d/%y %H:%M:%S");
  99.         case 'y':
  100.           ADDN(2,timeptr->tm_year%100);
  101.         case 'A':
  102.           ADDS(STR(DAY_1+timeptr->tm_wday));
  103.         case 'B':
  104.           ADDS(STR(MON_1+timeptr->tm_mon));
  105.         case 'C':
  106.           ADDS("%a %b %e %H:%M:%S %Y");
  107.         case 'D':
  108.           ADDS("%m/%d/%y");
  109.         case 'H':
  110.           ADDN(2,timeptr->tm_hour);
  111.         case 'I':
  112.           ADDN(2,timeptr->tm_hour%12+(timeptr->tm_hour%12==0)*12);
  113.         case 'M':
  114.           ADDN(2,timeptr->tm_min);
  115.         case 'R':
  116.           ADDS("%H:%M");
  117.         case 'S':
  118.           ADDN(2,timeptr->tm_sec);
  119.         case 'T':
  120.         case 'X':
  121.           ADDS("%H:%M:%S");
  122.         case 'U':
  123.           ADDN(2,(timeptr->tm_yday+7-timeptr->tm_wday)/7);
  124.         case 'W':
  125.           ADDN(2,(timeptr->tm_yday+7-(6+timeptr->tm_wday)%7)/7);
  126.         case 'Y':
  127.           ADDN(4,timeptr->tm_year+1900);
  128.         case 't':
  129.           STOR('\t');
  130.           break;
  131.         case 'n':
  132.           STOR('\n');
  133.           break;
  134.         case '%':
  135.           STOR('%');
  136.           break;
  137.         case '\0':
  138.           format--;
  139.           break;
  140.       }
  141.       size+=tmp;
  142.       s+=tmp;
  143.     }
  144.     else
  145.       STOR(*format);
  146.     format++;
  147.   }
  148.   STOR('\0');
  149.   if(size>maxsize)
  150.   { s-=size;
  151.     if(maxsize) /* Don't know if this is necessary, therefore it's here ;-) */
  152.       s[maxsize-1]='\0';
  153.     size=1;
  154.   }
  155.   return size-1;
  156. }
  157.  
  158.  
  159.  
  160. /****************** Setlocale **********************/
  161.  
  162. char *setlocale(int category,const char *name)
  163. { static char *string=NULL;
  164.   size_t i,a,b;
  165.   struct Locale *vec[5];
  166.   unsigned char *s1,*s2,c;
  167.   
  168.   if(string!=NULL) /* Free string if possible */
  169.   { free(string);
  170.     string=NULL; }  
  171.  
  172.   if(category<0||category>5)
  173.     return NULL;
  174.  
  175.   if(category==LC_ALL)
  176.   { a=0;
  177.     b=4; }
  178.   else
  179.     a=b=category-1;
  180.  
  181.   if(name==NULL) /* return name of current locale */
  182.   { size_t s=0;
  183.     for(i=a;i<=b;i++)
  184.       if(__localevec[i]!=NULL)
  185.         s+=strlen(__localevec[i]->loc_LocaleName);
  186.       else
  187.         s++; /* "C" locale */
  188.  
  189.     if((string=malloc(s+b-a+1))==NULL)
  190.       return NULL;
  191.  
  192.     string[0]='\0';
  193.     for(i=a;i<=b;i++)
  194.     { if(__localevec[i]!=NULL)
  195.         strcat(string,__localevec[i]->loc_LocaleName);
  196.       else
  197.         strcat(string,"C");
  198.       if(i!=b)
  199.         strcat(string,"\n");
  200.     }
  201.     return string;
  202.   }
  203.  
  204.   if((string=malloc(strlen_plus_one(name)))==NULL) /* gets freed next time */
  205.     return NULL;
  206.   strcpy(string,name);
  207.  
  208.   s1=s2=string;
  209.   for(i=a;i<=b;i++)
  210.   { while(*s2!='\0'&&*s2!='\n')
  211.       s2++;
  212.     c=*s2;
  213.     *s2='\0';
  214.     if(LocaleBase==NULL||(s1[0]=='C'&&s1[1]=='\0')) /* This is the only place */
  215.       vec[i]=NULL;                         /* LocaleBase gets tested for NULL */
  216.     else
  217.       if((vec[i]=OpenLocale(s1[0]=='\0'?NULL:s1))==NULL)
  218.       { for(;i-->a;)
  219.           CloseLocale(vec[i]);
  220.         return NULL; }
  221.     *s2=c;
  222.     if(c=='\0')
  223.       s2=string;
  224.     s1=s2;
  225.   }
  226.  
  227.   for(i=a;i<=b;i++)
  228.   { if(__localevec[i]!=NULL)
  229.       CloseLocale(__localevec[i]);
  230.     __localevec[i]=vec[i];
  231.   }
  232.  
  233.   if(__localevec[LC_MONETARY-1]!=NULL)
  234.   { struct Locale *locale=__localevec[LC_MONETARY-1];
  235.     __lconv_strftime.int_curr_symbol  =locale->loc_MonIntCS;
  236.     __lconv_strftime.currency_symbol  =locale->loc_MonCS;
  237.     __lconv_strftime.mon_decimal_point=locale->loc_MonDecimalPoint;
  238.     __lconv_strftime.mon_thousands_sep=locale->loc_MonGroupSeparator;
  239.     __lconv_strftime.mon_grouping     =locale->loc_MonFracGrouping;
  240.     __lconv_strftime.positive_sign    =locale->loc_MonPositiveSign;
  241.     __lconv_strftime.negative_sign    =locale->loc_MonNegativeSign;
  242.     __lconv_strftime.int_frac_digits  =locale->loc_MonIntFracDigits;
  243.     __lconv_strftime.frac_digits      =locale->loc_MonFracDigits;
  244.     __lconv_strftime.p_cs_precedes    =locale->loc_MonPositiveCSPos;
  245.     __lconv_strftime.p_sep_by_space   =locale->loc_MonPositiveSpaceSep;
  246.     __lconv_strftime.p_sign_posn      =locale->loc_MonPositiveSignPos;
  247.     __lconv_strftime.n_cs_precedes    =locale->loc_MonNegativeCSPos;
  248.     __lconv_strftime.n_sep_by_space   =locale->loc_MonNegativeSpaceSep;
  249.     __lconv_strftime.n_sign_posn      =locale->loc_MonNegativeSignPos;
  250.   }else
  251.   { __lconv_strftime.int_curr_symbol  ="";
  252.     __lconv_strftime.currency_symbol  ="";
  253.     __lconv_strftime.mon_decimal_point="";
  254.     __lconv_strftime.mon_thousands_sep="";
  255.     __lconv_strftime.mon_grouping     ="";
  256.     __lconv_strftime.positive_sign    ="";
  257.     __lconv_strftime.negative_sign    ="";
  258.     __lconv_strftime.int_frac_digits  =CHAR_MAX;
  259.     __lconv_strftime.frac_digits      =CHAR_MAX;
  260.     __lconv_strftime.p_cs_precedes    =CHAR_MAX;
  261.     __lconv_strftime.p_sep_by_space   =CHAR_MAX;
  262.     __lconv_strftime.p_sign_posn      =CHAR_MAX;
  263.     __lconv_strftime.n_cs_precedes    =CHAR_MAX;
  264.     __lconv_strftime.n_sep_by_space   =CHAR_MAX;
  265.     __lconv_strftime.n_sign_posn      =CHAR_MAX;
  266.   }
  267.  
  268.   if(__localevec[LC_NUMERIC-1]!=NULL)
  269.   { struct Locale *locale=__localevec[LC_NUMERIC-1];
  270.     __lconv_strftime.decimal_point=locale->loc_DecimalPoint;
  271.     __lconv_strftime.thousands_sep=locale->loc_GroupSeparator;
  272.   }else
  273.   { __lconv_strftime.decimal_point=".";
  274.     __lconv_strftime.thousands_sep=""; 
  275.   }
  276.   __decimalpoint=__lconv_strftime.decimal_point;
  277.  
  278.   if(__localevec[LC_TIME-1]!=NULL)
  279.     __gmtoffset=__localevec[LC_TIME-1]->loc_GMTOffset;
  280.   else
  281.     __gmtoffset=0;
  282.     
  283.   return (char *)name;
  284. }
  285.  
  286.  
  287. CONSTRUCTOR_P(initstrftime,200)
  288.     LocaleBase=(struct LocaleBase *)OpenLibrary("locale.library",37); /* Don't give up if this failes */
  289.  
  290.     if (setlocale(LC_ALL,"")!=NULL) /* Set the default locale */
  291.       return 0;
  292.  
  293.     exit(20);
  294. }
  295.  
  296. DESTRUCTOR_P(closestrftime,200)
  297. { int i;
  298.   for(i=0;i<5;i++)
  299.     if(__localevec[i]!=NULL)
  300.       CloseLocale(__localevec[i]);
  301.   
  302.   if(LocaleBase!=NULL)
  303.     CloseLibrary((struct Library *)LocaleBase);
  304. }
  305.  
  306. // ADD2INIT(__initlocale,-10);
  307. // ADD2EXIT(__exitlocale,-10);
  308.  
  309.  
  310.